import axios, {AxiosError, AxiosInstance, AxiosRequestConfig,AxiosResponse, InternalAxiosRequestConfig} from "axios";
import {TOKEN_HEADER} from "@/constant/app";



export interface BaseResult<T>{
     code: number
     msg: string
     data?: T 
}

interface GuiguRequestInterceptor{
    requestInterceptor?:(config:InternalAxiosRequestConfig)=>InternalAxiosRequestConfig
    requestInterceptorCatch?:(error:any)=>any
}

interface GuiguResponseInterceptor{
    responseInterceptor:(response:AxiosResponse)=>AxiosResponse
    responseInterceptorCatch:(response:AxiosError<BaseResult<any>,any>)=>any
}

class GuiguRequest{

    private instance:AxiosInstance

    private defaultRequestInterceptor:GuiguRequestInterceptor={
        requestInterceptor:(config)=>{
            config.headers[TOKEN_HEADER]="hahah"
            return config
        },
        requestInterceptorCatch:(error)=>{
            return Promise.reject({msg:error.message})
        }
    }

    private defaultResponseInterceptor:GuiguResponseInterceptor={
        responseInterceptor:response=>{
            const result:BaseResult<any> = response.data
            //如果后端返回错误状态码
            if(result.code!=200){
                return Promise.reject(result)
            }
        
            //正常返回
            return response.data
        },

        responseInterceptorCatch:error=>{

            alert(error.message)
    
            return Promise.reject({msg:"请求出错"})
        }
    }

    
    defaultSuccessFn(data:AxiosResponse<any>){
        return data
    }

    defaultErrorFn(error:BaseResult<any>){
        alert(error.msg)
    }
    constructor(config:AxiosRequestConfig){
        this.instance=axios.create(config)
        this.instance.interceptors.request.use(
            this.defaultRequestInterceptor?.requestInterceptor,
            this.defaultRequestInterceptor?.requestInterceptorCatch
            )
        this.instance.interceptors.response.use(
                this.defaultResponseInterceptor.responseInterceptor,
                this.defaultResponseInterceptor.responseInterceptorCatch
            )
    }
    static  create(config:AxiosRequestConfig) : GuiguRequest{
        return new GuiguRequest(config)
    }

    post(url?:string,data?:any,params?:any,config?:AxiosRequestConfig):Promise<BaseResult<any>>{
        if(!config){
            config={
                baseURL: import.meta.env.VITE_BASE_URL,
                timeout: 5000
            }
        }
        config!.url=url
        config!.data=data
        config!.params=params
        config!.method="post"
        return this.request(config)
    }

    get(url?:string,params?:any,config?:AxiosRequestConfig):Promise<BaseResult<any>>{
        if(!config){
            config={
                baseURL: import.meta.env.VITE_BASE_URL,
                timeout: 5000
            }
        }
        config!.url=url
        config!.params=params
        config!.method="get"
        return this.request(config)
    }

    put(url?:string,data?:any,params?:any,config?:AxiosRequestConfig):Promise<BaseResult<any>>{
        if(!config){
            config={
                baseURL: import.meta.env.VITE_BASE_URL,
                timeout: 5000
            }
        }
        config!.url=url
        config!.data=data
        config!.params=params
        config!.method='put'
        return this.request(config)
    }

    delete(url:string,data:any,params:any,config:AxiosRequestConfig):Promise<BaseResult<any>>{
        if(!config){
            config={
                baseURL: import.meta.env.VITE_BASE_URL,
                timeout: 5000
            }
        }
        config.url=url
        config.data=data
        config.params=params
        config.method='delete'
        return this.request(config)
    }
    request(config?:AxiosRequestConfig):any{
        return this.instance.request(config!)
        .then(this.defaultSuccessFn)
        .catch(this.defaultErrorFn)
    }
}

const config: AxiosRequestConfig= {
    baseURL: import.meta.env.VITE_BASE_URL,
    timeout: 5000
}

const guiguRequest=GuiguRequest.create(config)

export default guiguRequest


